package com.gitee.apanlh.web.model.vo;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gitee.apanlh.exp.ParamParserException;
import com.gitee.apanlh.util.base.ArrayUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.dataformat.XStreamUtils;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.web.model.Pager;
import com.gitee.apanlh.web.model.RequestDataType;
import com.gitee.apanlh.web.model.RequestHeader;
import com.gitee.apanlh.web.model.WebFile;

import java.util.List;
import java.util.Map;


/**
 * 	通用接收参数对象  
 * 	<br>包含Pager、File、JSON以及FORM混合参数XML等
 * 
 * 	@author Pan
 */
public class RequestVO {
	
	/** 存储键 */
	public static final String XML_KEY = "text-xml";
	public static final String TEXT_KEY = "text-content";
	
	/** 存放body内容 */
	private String body;
	/** 参数对象 */
	private Map<String, Object> params;
	/** 文件对象 */
	private WebFile webFile;
	/** 分页对象 */
	private Pager page;
	/** 请求头 */
	private RequestHeader header;
	/** 数据类型 */
	private RequestDataType dataType;
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	RequestVO() {
		super();
	}
	
	/**	
	 * 	构造函数-添加数据类型
	 * 	
	 * 	@author Pan
	 * 	@param 	header		请求头
	 * 	@param 	dataType	请求类型
	 * 	@param 	pager		分页对象
	 */
	public RequestVO(RequestHeader header, RequestDataType dataType, Pager pager) {
		this.header = header;
		this.dataType = dataType;
		this.page = pager;
	}
	
	/**	
	 * 	获取分页对象
	 * 	
	 * 	@author Pan
	 * 	@return	Pager
	 */
	public Pager getPage() {
		return page;
	}

	/**	
	 * 	获取请求头对象
	 * 	
	 * 	@author Pan
	 * 	@return	RequestHeader
	 */
	public RequestHeader getHeader() {
		return header;
	}

	/**		
	 * 	获取请求数据类型
	 * 	
	 * 	@author Pan
	 * 	@return	RequestDataType
	 */
	public RequestDataType getDataType() {
		return dataType;
	}

	/**	
	 * 	获取请求参数
	 * 	
	 * 	@author Pan
	 * 	@return	Map
	 */
	public Map<String, Object> getParams() {
		return params;
	}

	/**	
	 * 	设置文件对象
	 * 	
	 * 	@author Pan
	 * 	@param 	webFile	文件对象
	 */
	public void setWebFile(WebFile webFile) {
		this.webFile = webFile;
	}

	/**	
	 * 	获取请求体
	 * 	
	 * 	@author Pan
	 * 	@return	String
	 */
	public String getBody() {
		return body;
	}

	/**	
	 * 	设置请求体
	 * 	
	 * 	@author Pan
	 * 	@param	body	请求体
	 */
	public void setBody(String body) {
		this.body = body;
	}
	
	/**	
	 * 	设置JSON-MAP
	 * 	
	 * 	@author Pan
	 * 	@param 	map	 参数map
	 */
	public void setJsonParams(Map<String, Object> map) {
		params = map;
	}
	
	/**		
	 * 	设置默认MAP
	 * 	
	 * 	@author Pan
	 * 	@param 	map	参数map
	 */
	public void setParams(Map<String, String> map) {
		params = ClassConvertUtils.castMap(map);
	}

	/**	
	 * 	获取值
	 * 	<br>FORM表单发送转换String类型
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	Object
	 */
	public Object get(String key) {
		if (dataType.hasForm()) {
			return getStr(key);
		}
		return get(key, Object.class);
	}
	
	/**	
	 * 	获取值
	 * 	<br>自定义类型
	 * 	
	 * 	@author Pan
	 * 	@param 	<T>		T
	 * 	@param 	key		键
	 * 	@param 	clazz	类
	 * 	@return	T
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(String key, Class<T> clazz) {
		Object obj = params.get(key);
		if (dataType.hasJson()) {
			if (obj instanceof JSONObject) {
				return ((JSONObject) obj).toJavaObject(clazz);
			}
			if (obj instanceof JSONArray) {
				return ((JSONArray) obj).toJavaObject(clazz);
			}
		}
		return obj == null ? null : (T) obj;
	}
	
	/**
	 * 	获取值
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	String
	 */
	public String getStr(String key) {
		return get(key, String.class);
	}
	
	/**
	 * 	获取值
	 * 	<br>FORM表单发送转换对应类型
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	Integer
	 */
	public Integer getInt(String key) {
		if (dataType.hasJson()) {
			return get(key, Integer.class);
		}
		String value = getStr(key);
		
		if (value == null) {
			return null;
		}
		return ClassConvertUtils.toInt(value);
	}
	
	/**	
	 * 	获取JSON对象
	 * 	<br>可连续.对象
	 * 	<br>例如user.phone(等于获取user中phone属性)
	 * 	<br>例如user.children.phone(等于获取例如user里children对象的phone属性)
	 * 	
	 * 	@author Pan
	 * 	@param 	<T>		数据类型
	 * 	@param 	key		键
	 * 	@param 	clazz	返回类型
	 *	@return T
	 */
	public <T> T getJsonObject(String key, Class<T> clazz) {
		//	如果不存在后续对象情况直接返回
		if (key.indexOf('.') == -1) {
			return get(key, clazz);
		}
		return find(key, clazz);
	}
	
	/**		
	 * 	获取字符串数组
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	String[]
	 */
	public String[] getArrayStr(String key) {
		if (dataType.hasJson()) {
			return getJsonObject(key, String[].class);
		}
		return StringUtils.split(get(key, String.class), ",");
	}
	
	/**		
	 * 	获取整型数组
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	Integer[]
	 */
	public Integer[] getArrayInt(String key) {
		if (dataType.hasJson()) {
			return getJsonObject(key, Integer[].class);
		}
		return ArrayUtils.toIntWrapper(StringUtils.split(get(key, String.class), ","));
	}
	
	/**	
	 * 	获取文件对象
	 * 	
	 * 	@author	pan
	 * 	@return	WebFile
	 */
	public WebFile getWebFile() {
		return this.webFile;
	}
	
	/**	
	 * 	获取文本
	 * 	
	 * 	@author Pan
	 * 	@return	String
	 */
	public String getText() {
		return getStr(TEXT_KEY);
	}
	
	/**	
	 * 	获取XML
	 * 	
	 * 	@author Pan
	 * 	@return	String
	 */
	public String getXml() {
		return getStr(XML_KEY);
	}
	
	/**	
	 * 	将XMl返回的值转换为Bean
	 * 	默认body别名为{@code <data>xxx</data>}
	 * 	
	 * 	@author Pan
	 * 	@param 	<T>		数据类型
	 * 	@param 	clazz	类
	 * 	@return	T
	 */
	public <T> T getXml(Class<T> clazz) {
		return getXml(clazz, "data");
	}
	
	/**	
	 * 	将XMl返回的值转换为Bean
	 * 	<br>自定义body别名
	 * 	
	 * 	@author Pan
	 * 	@param 	<T>			数据类型
	 * 	@param 	clazz		类
	 * 	@param 	bodyAlias	别名
	 * 	@return	T
	 */
	public <T> T getXml(Class<T> clazz, String bodyAlias) {
		return XStreamUtils.toBean(XStreamUtils.filterXml(getXml(), bodyAlias), clazz);
	}
	
	/**	
	 * 	将获取的值转化对象
	 * 	<br>不存在的属性将忽略
	 * 	<br>接收FORM表单,将自动转换相对应类型(如果类型传递int，但实体接收String最终结果为String)
	 * 	<br>接收JSON,注意传递必须与实体接收参数类型一致(如不对应则出现参数异常)
	 * 	
	 * 	@author Pan
	 * 	@param 	<T>		数据类型
	 * 	@param 	clazz	类
	 * 	@return	T
	 */
	public <T> T toBean(Class<T> clazz) {
		try {
			if (dataType.hasJson()) {
				return JsonUtils.toBean(body, clazz);
			}
			return ClassConvertUtils.toBean(params, clazz);
		} catch (Exception e) {
			throw new ParamParserException(e.getMessage(), e);
		}
	}

	/**
	 * 	将获取的值转化集合对象
	 * 	<br>不存在的属性将忽略
	 * 	<br>只能接收JSON,注意传递必须与实体接收参数类型一致(如不对应则出现参数异常)
	 *
	 * 	@author Pan
	 * 	@param 	<T>		数据类型
	 * 	@param 	clazz	类
	 * 	@return	List
	 */
	public <T> List<T> toListBean(Class<T> clazz) {
		try {
			if (dataType.hasJson()) {
				return JsonUtils.toList(body, clazz);
			}
			return null;
		} catch (Exception e) {
			throw new ParamParserException(e.getMessage(), e);
		}
	}

	/**	
	 * 	搜索JSON子对象
	 * 	<br>如果不存在Key值则出现最后一次的值
	 * 	
	 * 	@author Pan
	 * 	@param 	key		键
	 * 	@param 	clazz	类
	 * 	@return	T
	 */
	@SuppressWarnings("unchecked")
	private <T> T find(String key, Class<T> clazz) {
		int index = 0;
		String[] keys = StringUtils.split(key, ".");
		Object object = params.get(keys[index]);
		while (index < keys.length) {
			if (object instanceof JSONObject && index != 0) {
				JSONObject jsonObject = (JSONObject) object;
				object = jsonObject.get(keys[index]);
			}
			if (index == (keys.length - 1)) {
				break;
			}
			index ++;
		}
		if (object instanceof JSONArray) {
			return ((JSONArray) object).toJavaObject(clazz);
		}
		if (object instanceof JSONObject) {
			return ((JSONObject) object).toJavaObject(clazz);
		}
		return (T) object;
	}
	
	@Override
	public String toString() {
		return "RequestVO [page=" + page + ", params=" + params + "]";
	}
}
